﻿using System;
using breakoutsharp.core;
using breakoutsharp.visual;
using breakoutsharp.visual.gameobject;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Drawing;

namespace breakoutsharp.core
{
    public class Renderer : IDisposable
    {
        protected BreakoutEngine game;
        protected Device device;

        protected float zoomZ = (float)((300f) / (Math.Tan((Math.PI / 4f) / 2f)));
        protected Size size;
        protected Size resolution;

		protected DxSprite background;
		protected Sprite sprite;

        /// <summary>
        /// Public constructor
        /// </summary>
        /// <param name="engine">The game engine.</param>
        /// <param name="dev">the graphics device.</param>
        public Renderer(BreakoutEngine engine, Device dev, Size size, Size resolution)
        {
#if DEBUG
            if (engine == null)
            {
                throw new ArgumentException("engine cannot be null");
            }

            if (dev == null)
            {
                throw new ArgumentException("device cannot be null");
            }
#endif 

            this.size = size;
            this.resolution = resolution;
            game = engine;
            device = dev;

			background = new DxSprite(device, @"gfx\", "bg1", this.size);
			sprite = new Sprite(device);
        }

        /// <summary>
        /// Sets up the camera properties alongside with various other renderstate properties such as culling and lightning
        /// </summary>
        public void SetupCamera()
        {
            /* Using counterclockwise culling to improve performance */
			device.RenderState.CullMode = Cull.None;

            device.Transform.Projection = Matrix.PerspectiveFovLH(System.Convert.ToSingle(Math.PI) / 4, (float)size.Width / size.Height, 1f, 10000f);
            device.Transform.View = Matrix.LookAtLH(new Vector3((float)resolution.Width / 2, -1 * (float)resolution.Height / 2, -1 * zoomZ), new Vector3((float)resolution.Width / 2, -1 * (float)resolution.Height / 2, 0), new Vector3(0, 1, 0));
            device.RenderState.Lighting = false;

			/* Transparency */
			device.RenderState.AlphaBlendEnable = true;
            device.RenderState.SourceBlend = Blend.SourceAlpha;
            device.RenderState.DestinationBlend = Blend.InvSourceAlpha;
			device.RenderState.AlphaTestEnable = true;
            device.RenderState.ReferenceAlpha = 0x8;
			device.RenderState.AlphaFunction = Compare.GreaterEqual;


			device.TextureState[0].ColorOperation = TextureOperation.Modulate;
			device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
            device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
			device.TextureState[0].AlphaOperation = TextureOperation.Modulate;
			device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor;
			device.TextureState[0].AlphaArgument2 = TextureArgument.Diffuse;
        }

        /// <summary>
        /// Draws all visible objects contained within the current game
        /// </summary>
        public void RenderObjects()
        {
			background.Draw(sprite, new Rectangle(0, 0, size.Width, size.Height), 0, 0, size);

			foreach (Ball b in game.Balls)
			{
				if (b.Alive)
					b.Draw(device);
			}

			foreach (Paddle p in game.Paddles)
			{
				if (p.Alive)
					p.Draw(device);
			}


            foreach (Block b in game.Blocks)
            {
                if (!b.Dead)
                    b.Draw(device);
            }
        }

        public void RenderGameOver()
        {
            
        }

		public void Dispose()
		{
			sprite.Dispose();
			background.Dispose();
			device = null;
			game = null;
		}
	}
}
